这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 软件与操作系统 » 悠龙(μTenux系统)开发进程贴--智能--物联

共46条 3/5 1 2 3 4 5 跳转至
高工
2013-07-25 07:33:46     打赏
21楼

3. 实验二 (信号量)       【回到开发进程列表


1. 概念学习

   作用

        多任务系统中的各个任务在共享各类资源时,因为有些资源一次只能被一个任务使用, 为防止同时运行的多个任务出现资源争执的需要, 系统提供了资源排他机制 - 信号量。 

        先定义信号量关联的资源数,对资源进行使用的任务先进行资源查询,如果能够从信号量中获得资源,任务将继续处理,在不需要使用资源时,便释放资源。 

        如果不能从信号量中获得到所要的资源,任务便不能继续执行,迁移到 wait 状态,并进入信号量的等待队列中,处于等待的过程中的任务,如果可以得到资源,任务便从等待状态中脱出,迁移ready 状态。 

   属性 

         一个计数信号量:是一个 32 位的变量,初始值表示可以使用的资源数量,初始值为 0 表示资源开始处于锁住状态,一个非 0 的值表示有多个资源供多个任务访问。 

        等待信号量的 Task 的等待队列。等待队列属性可以是 FIFO 或者Priority 方式 

   相关函数

        创建信号量: ID semid = tk_cre_sem ( T_CSEM *pk_csem )

        释放信号量: ER ercd = tk_sig_sem ( ID semid, INT cnt ) 

        等待信号量: ER ercd = tk_wai_sem ( ID semid, INT cnt, TMO tmout ) 

        删除信号量: ER ercd = tk_del_sem ( ID semid ) 

        查询信号量:ER ercd = tk_ref_sem ( ID semid, T_RSEM *pk_rsem )


2. 实验操作

       在实验的例程中创建了三个任务:初始化任务、任务A和任务B,其优先级顺序为A->B->初始化任务;

       在初始化任务中分别创建了任务A,B以及一个信号量,且信号量初始化资源数为10;

       在完成任务A,B及信号量的创建后优先启动了B任务,然后在B任务中必须先启动A任务;

       在A任务的启动过程中需要等待一刚刚创建的信号量10个资源当中的一个资源,而此时10个资源都未被其他任务使用,所以A任务启动成功;

       A任务启动成功后使会释放信号量,而且之后任务B启动也需要等待该任务量,如上面一样信号量资源充足,任务B启动成功,然后释放信号量,显示信号量资源数,唤醒任务A,未得到命令则循环这一步;

       之后便是在任务B退出过程中删除信号量,任务A以及删除自身,关闭系统;

       以上便是整个工作流程。

任务A代码 

void SemSampleTaskA(W stacd,VP exinf)
{
    ER ercd;

    tm_putstring((UB*)"Task A is starting;\n");    // 指示任务A启动

  // 进入任务A循环
    for(;;){
        tm_putstring((UB*)"Task A is waiting semaphore;\n");  // 等待信号量

        ercd = tk_wai_sem(semid, 1, -1);   // 等待一个资源,直到该资源可用为止
        SemSamplePutCnt();
        if (E_OK == ercd){
            tm_putstring((UB*)"Task A get semaphore successfully;\n");
        }else{
            tm_putstring((UB*)"Task A can't get semaphore;\n");
            PutErcd(ercd);   // 显示错误代码
        }

        tm_putstring((UB*)"Task A release semaphore;\n");
        ercd = tk_sig_sem(semid, 1);  // 释放信号量,释放一个资源数
        SemSamplePutCnt();
        if (E_OK == ercd){
            tm_putstring((UB*)"Task A release semaphore successfully;\n");
        } else {
            tm_putstring((UB*)"Task A can't release semaphore;\n");
        }

        tm_putstring((UB*)"Task A enter sleep status;\n");
        tk_slp_tsk(-1);
    }
}

 

任务B代码 

 

void SemSampleTaskB(W stacd,VP exinf)
{
    ER ercd;
    B c;

    ercd = tk_sta_tsk(TaskID_A,0);
    if (E_OK == ercd){
        tm_putstring((UB*)"Task B start Task A successfully;\n");
    } else {
        tm_putstring((UB*)"Task B can't start Task A;\n");
    }

    for(;;){
        tm_putstring((UB*)"Task B is waiting semaphore;\n");

        ercd = tk_wai_sem(semid, 1, -1);
        SemSamplePutCnt();
        if (E_OK == ercd){
            tm_putstring((UB*)"Task B get semaphore successfully;\n");
        } else {
            tm_putstring((UB*)"Task B can't get semaphore;\n");
         PutErcd(ercd);
        }

        tm_putstring((UB*)"Input Command(e=exit):\n");
        c = tm_getchar(0);
        if('e' == c) {
            tm_putstring((UB*)"Exit from all task;\n");
            break;
        } else {
            tm_putstring((UB*)"Task B release semaphore;\n");
            ercd = tk_sig_sem(semid, 1);
            SemSamplePutCnt();
            if (E_OK == ercd){
          tm_putstring((UB*)"Task B release semaphore successfully;\n");
        } else {
            tm_putstring((UB*)"Task B can't release semaphore;\n");
        }

            tm_putstring((UB*)"Task B wake up Task A;\n");
            tk_wup_tsk(TaskID_A);
        }
    }

    tm_putstring((UB*)"Task B delete semaphore;\n");
    ercd = tk_del_sem(semid);
    if (ercd == E_OK){
        tm_putstring((UB*)"Task B delete semaphore successfully;\n");
    } else {
        tm_putstring((UB*)"Task B can't delete semaphore;\n");
    }

    tm_putstring((UB*)"Task B will terminate&delete task A;\n");
    tk_ter_tsk(TaskID_A);
    tk_del_tsk(TaskID_A);
    tm_putstring((UB*)"Task B will terminate&delete self;\n");
    tk_exd_tsk();


高工
2013-07-26 07:59:32     打赏
22楼

4. 实验三 (事件标志)    【回到开发进程列表


1. 概念学习

    >事件标志的作用

        事件标志主要是用来让一个任务可以判断一个事件是否发生,以决定是继续执行某些操作还是进入等待状态。除了等待事件标志的任务,还至少有一个中断或者其他的任务用于改变事件标志,让等待的任务进入就绪态,进而重新运行。

        等待信号的任务对事件标志进行判断, 如果事件标志的位模式与等待位模式一致时, 等待任务退出等待状态, 继续进行处理,如果不一致,任务就进入或者继续 wait 状态。 

    >事件标志的属性

        事件标志是一个32位的变量,其每一位都标志一个事件且有置位和清除两种状态,一般情况下当一个位置位时,表示其标志的事件已经发生了。等待事件标志的任务可以是以先入先出的方式也可以是以优先级排列的方式。

    >事件标志的相关函数

         创建事件标志: ID flgid = tk_cre_flg ( T_CFLG *pk_cflg ) 

             设置事件标志: ER ercd = tk_set_flg ( ID flgid, UINT setptn ) 

             清除事件标志: ER ercd = tk_clr_flg ( ID flgid, UINT clrptn ) 

             删除事件标志: ER ercd = tk_del_flg ( ID flgid ) 

             等待事件标志: ER ercd = tk_wai_flg ( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn,TMO tmout ) 


             查询事件标志: ER ercd = tk_ref_flg ( ID flgid, T_RFLG *pk_rflg ) 



2. 实验操


运行效果:

----------------------------------------------------

        micro Tenux Version 1.6.00(build 0180)      
         Supported MCU is ATMEL AT91SAM3S4C         
  Copyright(c) 2008-2013 by Dalian uLoong Co.,Ltd.  
----------------------------------------------------


Eventflag sample create step 1-Create T eventflag, ID is 1 !
Eventflag sample create step 2-Create Task A, ID is 2 !
Eventflag sample create step 3-Create Task B, ID is 3 !
Eventflag sample create step 4-Start Task B;


Task B will start task A;
Task B is running,input Command(e=exit):
Task A is now get eventflag 0x00000001 1 times
Task A is now clr eventflag 0x00000001
======================================
Task A  will  set eventflag 0x00000002
Task A  now  set  eventflag 0x00000002
Now Flag pattern is 0x00000002


Task B is now get eventflag 0x00000002 1 times
Task B is now clr eventflag 0x00000002
======================================
Task B  will  set eventflag 0x00000001
Task B   now  set eventflag 0x00000001
Now Flag pattern is 0x00000001


Task B is running,input Command(e=exit):
Task A is now get eventflag 0x00000001 2 times
Task A is now clr eventflag 0x00000001
======================================
Task A  will  set eventflag 0x00000002
Task A  now  set  eventflag 0x00000002
Now Flag pattern is 0x00000002


Task B is now get eventflag 0x00000002 2 times
Task B is now clr eventflag 0x00000002
======================================
Task B  will  set eventflag 0x00000001
Task B   now  set eventflag 0x00000001
Now Flag pattern is 0x00000001


Task B is running,input Command(e=exit):
Task A is now get eventflag 0x00000001 3 times
Task A is now clr eventflag 0x00000001
======================================
Task A  will  set eventflag 0x00000002
Task A  now  set  eventflag 0x00000002
Now Flag pattern is 0x00000002


Task B is now get eventflag 0x00000002 3 times
Task B is now clr eventflag 0x00000002
======================================
Task B  will  set eventflag 0x00000001
Task B   now  set eventflag 0x00000001
Now Flag pattern is 0x00000001


Task B is running,input Command(e=exit):
Task A is now get eventflag 0x00000001 4 times
Task A is now clr eventflag 0x00000001
======================================
Task A  will  set eventflag 0x00000002
Task A  now  set  eventflag 0x00000002
Now Flag pattern is 0x00000002


Task B is now get eventflag 0x00000002 4 times
Task B is now clr eventflag 0x00000002
======================================
Task B  will  set eventflag 0x00000001
Task B   now  set eventflag 0x00000001
Now Flag pattern is 0x00000001


Task B is running,input Command(e=exit):
Task A is now get eventflag 0x00000001 5 times
Task A is now clr eventflag 0x00000001
======================================
Task A  will  set eventflag 0x00000002
Task A  now  set  eventflag 0x00000002
Now Flag pattern is 0x00000002


Task B is now get eventflag 0x00000002 5 times
Task B is now clr eventflag 0x00000002
======================================
Task B  will  set eventflag 0x00000001
Task B   now  set eventflag 0x00000001
Now Flag pattern is 0x00000001


Task B is running,input Command(e=exit):



从上面的运行效果来看呢,整个程序在运行过程中不管任务A还是任务B都会记录并回显其获取到的事件标志的值及获取成功的次数,具体的还是看一下程序。




3. 程序分析

     1. 任务A的代码


void EventflagSampleTaskA(W stacd,VP exinf)
{
ER ercd;
    UINT i,flgptn;
 
    for(i=0;;i++) {
        tk_wai_flg(FlgID,1,TWF_ANDW ,&flgptn,-1);   // 与的方式等待事件标志Flg_ID中最低位置位
        tm_putstring((UB*)"Task A is now get eventflag 0x00000001 ");
        tm_putchar(i+48+1);
        tm_putstring((UB*)" times\n");
        tk_clr_flg(FlgID,0xFFFE);   // 清除事件标志变量的最低位
        tm_putstring((UB*)"Task A is now clr eventflag 0x00000001\n");
        Delay(0x1000000);
        tm_putstring((UB*)"======================================\n");
        Delay(0x1000000);
        tm_putstring((UB*)"Task A  will  set eventflag 0x00000002\n");
        ercd=tk_set_flg(FlgID,2); // 置位事件标志变量的第二位,用于任务B使用
        if(E_OK == ercd){
            tm_putstring((UB*)"Task A  now  set  eventflag 0x00000002\n");
        }

         else {
        tm_putstring((UB*)"Task A cannot set eventflag 0x00000002\n");
        PutErcd(ercd);
        }
        EventflagSamplePutFlg();
        tm_putstring((UB*)"\n");
    }
}

2. 任务B的代码

void EventflagSampleTaskB(W stacd,VP exinf)
{
    B c;
    ER ercd;
    UINT i,flgptn;

tm_putstring((UB*)"Task B will start task A;\n");
tk_sta_tsk(TaskID_A,0);   // 在进入任务循环前启动任务A


    for(i=0;;i++) {
    tm_putstring((UB*)"Task B is running,input Command(e=exit):\n");
    c = tm_getchar(0);
    if(c=='e') {
    break;
    }
        tk_wai_flg(FlgID,2,TWF_ANDW ,&flgptn,-1);   // 等待事件标志的第二位置全
        tm_putstring((UB*)"Task B is now get eventflag 0x00000002 ");
        tm_putchar(i+48+1);
        tm_putstring((UB*)" times\n");
        tk_clr_flg(FlgID,0xFFFD);  // 使用完成后清除事件标志第二位
        tm_putstring((UB*)"Task B is now clr eventflag 0x00000002\n");
        Delay(0x1000000);
        tm_putstring((UB*)"======================================\n");
        Delay(0x1000000);
        tm_putstring((UB*)"Task B  will  set eventflag 0x00000001\n");
        ercd=tk_set_flg(FlgID,1);   // 置位事件标志第一位用于任务A
        if(E_OK == ercd){
        tm_putstring((UB*)"Task B   now  set eventflag 0x00000001\n");
        } else {
        tm_putstring((UB*)"Task B cannot set eventflag 0x00000001\n");
        PutErcd(ercd);
        }
        EventflagSamplePutFlg();
        tm_putstring((UB*)"\n");
    }

    tm_putstring((UB*)"Task B will delete flag;\n");
    tk_del_flg(FlgID);
    tm_putstring((UB*)"Task B will terminate&delete task A;\n");
    tk_ter_tsk(TaskID_A);
    tk_del_tsk(TaskID_A);
    tm_putstring((UB*)"Task B will terminate&delete self;\n");
    tk_exd_tsk();
}



4. 思考题


    1. 更换为中断后一般是单向传递,即由中断来置位,任务来清零。结果是只有中断事件发生后,任务才得以继续执行对应的操作。

    2. 如果将其中一个任务优先级提高的话,这里将任务A优先级改为11,则B任务优先级提高。这种情况下的执行顺序:B启动A->B执行->B等待->A等待(因为初始事件标志就为1,所以通过)->A置位事件标志第二位->B执行,然后如些循环。所以可以看出,这种功能适合于需要低优先级任务在高做先级任务某步前做准备处理时使用。


高工
2013-07-26 09:55:54     打赏
23楼

5. 实验四 (邮箱)     【回到开发进程列表


1. 概念学

    用途:

        邮箱实现任务之间的通信功能,邮箱包含有多任务应用的等待队列和邮

箱专用的信息等待队列。 

        首先分配发送消息的任务(发送任务)和接受消息的任务(接受任务)。

        如果邮箱里已经有任务被排列在队列里,消息就会被传递给等待队列里的先头任务中,收到信息的任务将会从 Wait 状态迁移到 Ready 状态。 

        如果邮箱中还没有任务被排列在队列中,消息就会被排列到消息队列中。发行消息的任务不进行状态迁移。 

        需要接受消息的任务对邮箱发行 tk_rcv_msg 系统调用, 如果邮箱中已经有消息排列在队列里时,任务就会收取排列在队列里的消息。如果邮箱中还没有消息被排列在队列中,任务就不能继续处理,被排列在邮箱

的任务等待队列中,迁移到 wait 状态。在处于 wait 状态过程中,如果从其他任务那里得到消息的话,可以接受消息,任务同时也会从 wait 状态解脱出来,迁移到 ready 状态。 

    构成及属性:

        发送消息的消息队列: 

        等待接受消息的任务队列:等待队列属性可以是 FIFS 或者 Priority 方式 

    相关函数:

        接受邮箱中的消息: ER ercd = tk_rcv_mbx ( ID mbxid, T_MSG **ppk_msg, TMO tmout ) 

        删除邮箱: ER ercd = tk_del_mbx ( ID mbxid ) 

        查询邮箱: ER ercd = tk_ref_mbx ( ID mbxid, T_RMBX *pk_rmbx ) 



2. 实验操作

        先上效果图:

串口回显效果图


相关代码:


ER MbxSample( void)
{
    ER ercd=E_OK;
    T_CTSK ctsk;
    T_CMBX cmbx;


    tm_putstring((UB*)"Mailbox sample create step 1-Create Task A;\n");
    ctsk.exinf = (VP)NULL;
    ctsk.tskatr = TA_HLNG|TA_RNG0;
    ctsk.task = MbxSampleTaskA;
    ctsk.itskpri = 20;
    ctsk.stksz = 512;
    TaskID_A = tk_cre_tsk(&ctsk);  // 创建任务A
    if(TaskID_A < E_OK) {
        ercd=TaskID_A;
        tm_putstring((UB*)"Task A can't creat;\n");
        PutErcd(ercd);
        return ercd;
    }
    
    tm_putstring((UB*)"Mailbox sample create step 2-Create Task B;\n");
    ctsk.exinf = (VP)NULL;
    ctsk.tskatr = TA_HLNG|TA_RNG0;
    ctsk.task = MbxSampleTaskB;
    ctsk.itskpri = 24;
    ctsk.stksz = 512;
    TaskID_B = tk_cre_tsk(&ctsk);  // 创建任务B
    if(TaskID_B < E_OK) {
        ercd=TaskID_B;
        tm_putstring((UB*)"Task B can't creat;\n");
        PutErcd(ercd);
        return ercd;
    }
    
    tm_putstring((UB*)"Mailbox sample create step 3-Create a send mailbox;\n");
    cmbx.exinf = (VP)NULL;
    cmbx.mbxatr = TA_TFIFO|TA_MFIFO;
    MbxID_S = tk_cre_mbx(&cmbx);   // 创建邮箱发送
    if(MbxID_S < E_OK){
        ercd=MbxID_S;
        tm_putstring((UB*)"MailBox_Send can't creat;\n");
        PutErcd(ercd);
        return ercd;
    }


    tm_putstring((UB*)"Mailbox sample create step 4-Create a return mailbox;\n");
    cmbx.exinf = (VP)NULL;
    cmbx.mbxatr = TA_TFIFO|TA_MFIFO;
    MbxID_R = tk_cre_mbx(&cmbx);   // 创建邮箱接收
    if(MbxID_R < E_OK){
      ercd=MbxID_R;
      tm_putstring((UB*)"MailBox_Recieve can't creat;\n");
      PutErcd(ercd);
      return ercd;
    }


    tm_putstring((UB*)"Mailbox sample create step 5-Start Task A;\n");
    ercd = tk_sta_tsk(TaskID_A,0);  // 开始任务A
    if (E_OK != ercd){
        tm_putstring((UB*)"start Task A failed;\n");
        PutErcd(ercd);
    }
    return TRUE;



/*
 *    Function Name : MbxSampleTaskA
 *    Create Date   : 2012/9/24-2013/6/8
 *    Author        : Dengjk-Wangl
 *    Description   : Task A loop function.
 *    Param         : stacd:parameter from start task
 *                  : exinf:
 *    Return Code   : None.
 */
void MbxSampleTaskA(W stacd,VP exinf)
{
    B c;
    ER ercd;
    U_MSG *pk_rcvmsg;
    U_MSG sndmsg;


    tm_putstring((UB*)"Mailbox sample create step 6-Start Task B;\n\n");
    ercd = tk_sta_tsk(TaskID_B,0);  // 启动任务B
    if (E_OK != ercd){
        tm_putstring((UB*)"Task B is starting failed;\n");
        PutErcd(ercd);
    }


    for(;;){
        tm_putstring((UB*)"Task A is running,Input Command(e=exit):\n");
        c = tm_getchar(0);
        if('e' == c) {
            break;
        }


        sndmsg.usrmsg = "1-2-3,Please Starting up....\n";
        tm_putstring((UB*)"Task A send a message to Task B:");
        tm_putstring((UB*)sndmsg.usrmsg);
        ercd = tk_snd_mbx(MbxID_S,(T_MSG*)&sndmsg);  // 发送邮箱信息
        if(E_OK == ercd){
            tm_putstring((UB*)"Task A sent a message successfully;\n");
        }else{
            tm_putstring((UB*)"Task A can't send a message;\n");
            PutErcd(ercd);
        }


        tm_putstring((UB*)"Task A is waiting Task B return message;\n\n");
        ercd = tk_rcv_mbx(MbxID_R,(T_MSG**)&pk_rcvmsg,-1);
        if(E_OK == ercd){
            tm_putstring((UB*)"Task A have received return message: ");
            tm_putstring((UB*)pk_rcvmsg->usrmsg);
        }else{
            tm_putstring((UB*)"Task A can't receive return message: \n");
            PutErcd(ercd);
        }
    }


    tm_putstring((UB*)"Task A will delete mailbox;\n");
    tk_del_mbx(MbxID_S);
    tk_del_mbx(MbxID_R);
    tm_putstring((UB*)"Task A will terminate&delete task B;\n");
    tk_ter_tsk(TaskID_B);
    tk_del_tsk(TaskID_B);
    tm_putstring((UB*)"Task A will terminate&delete self;\n");
    tk_exd_tsk();
}


任务B代码:


void MbxSampleTaskB(W stacd,VP exinf)
{
    ER ercd;
    U_MSG *pk_rcvmsg;
    U_MSG sndmsg;


    for(;;){
        tm_putstring((UB*)"Task B is waiting a message;\n");
        ercd = tk_rcv_mbx(MbxID_S,(T_MSG**)&pk_rcvmsg,-1);  // 接收邮箱信息
        if(E_OK == ercd){
            tm_putstring((UB*)"Task B have received a message: ");
            tm_putstring((UB*)pk_rcvmsg->usrmsg);
        }else{
            tm_putstring((UB*)"Task B can't receive a message: ");
            PutErcd(ercd);
        }


        sndmsg.usrmsg = "I have got up...\n";
        tm_putstring((UB*)"Task B return a message to Task A:");
        tm_putstring((UB*)sndmsg.usrmsg);
        tm_putstring((UB*)"\n");
        ercd = tk_snd_mbx(MbxID_R,(T_MSG*)&sndmsg);  // 发送邮箱信息
        if(E_OK != ercd){
            tm_putstring((UB*)"Task B can't return a message;\n");
            PutErcd(ercd);
        }
    }
}


任务A代码:


void MbxSampleTaskA(W stacd,VP exinf)
{
    B c;
    ER ercd;
    U_MSG *pk_rcvmsg;
    U_MSG sndmsg;


    tm_putstring((UB*)"Mailbox sample create step 6-Start Task B;\n\n");
    ercd = tk_sta_tsk(TaskID_B,0);  // 启动任务B
    if (E_OK != ercd){
        tm_putstring((UB*)"Task B is starting failed;\n");
        PutErcd(ercd);
    }


    for(;;){
        tm_putstring((UB*)"Task A is running,Input Command(e=exit):\n");
        c = tm_getchar(0);
        if('e' == c) {
            break;
        }


        sndmsg.usrmsg = "1-2-3,Please Starting up....\n";
        tm_putstring((UB*)"Task A send a message to Task B:");
        tm_putstring((UB*)sndmsg.usrmsg);
        ercd = tk_snd_mbx(MbxID_S,(T_MSG*)&sndmsg);  // 发送邮箱信息
        if(E_OK == ercd){
            tm_putstring((UB*)"Task A sent a message successfully;\n");
        }else{
            tm_putstring((UB*)"Task A can't send a message;\n");
            PutErcd(ercd);
        }


        tm_putstring((UB*)"Task A is waiting Task B return message;\n\n");
        ercd = tk_rcv_mbx(MbxID_R,(T_MSG**)&pk_rcvmsg,-1);
        if(E_OK == ercd){
            tm_putstring((UB*)"Task A have received return message: ");
            tm_putstring((UB*)pk_rcvmsg->usrmsg);
        }else{
            tm_putstring((UB*)"Task A can't receive return message: \n");
            PutErcd(ercd);
        }
    }


    tm_putstring((UB*)"Task A will delete mailbox;\n");
    tk_del_mbx(MbxID_S);
    tk_del_mbx(MbxID_R);
    tm_putstring((UB*)"Task A will terminate&delete task B;\n");
    tk_ter_tsk(TaskID_B);
    tk_del_tsk(TaskID_B);
    tm_putstring((UB*)"Task A will terminate&delete self;\n");
    tk_exd_tsk();
}


程序说明:


    A,B任务及邮箱都由ER MbxSample( void)创建,在该函数的最后启动的任务A;而A任务启动后先启动任务B然后发送邮箱信息,并开始等待B任务返回邮箱信息。任务B则是启动后就开始接收任务A的邮箱信息然后返回邮箱信息,如此循环。


院士
2013-07-26 10:28:43     打赏
24楼

嘿嘿,还有几天就要结束了。

我也要抓紧时间了。


高工
2013-07-26 10:32:58     打赏
25楼
那还有几天呢?

高工
2013-07-26 10:34:06     打赏
26楼

看来真的得加快速度了,还要加GUI进去,以前没怎么搞过GUI,这次一定得搞定一个进去至少。


高工
2013-07-29 10:10:18     打赏
27楼
加油,马上到月底了……

院士
2013-07-30 10:17:20     打赏
28楼

月底就要到了……

捉急啊~~


高工
2013-07-31 08:00:54     打赏
29楼

6. 实验五 (互斥体)    【返回开发进程列表】


  1. 概念学习


      互斥体在一个任务要独占且使用某个共享资源时使用,可以确保数据在使用过程中不被其他任务更改或破坏。使用互斥体遵循互锁机制,即几个任务可以根据优先有和互斥体的当前状态轮流使用互斥体。而没有拿到互斥体使用权的任务需要等待其他任务使用完后才有可能得到使用权独占互斥体一段时间。

    在互斥体使用过程中不注意的话可能发生“死锁”的情况,让系统状态变得非常糟糕。因此系统提供了优先级反转的方法。

    属性

         每个互斥体都有一个状态(锁定和解锁),和一个等待互斥体的任务队列。 


         互斥体属性TA_INHERIT(=0x02), 支持优先级继承
        互斥体属性TA_CEILING(=0x03), 支持顶置优先级 

    相关函数

        创建互斥体: ID mtxid = tk_cre_mtx(T_CMTX *pk_cmtx) 

        删除互斥体: ER ercd = tk_del_mtx ( ID mtxid ) 
        锁定互斥体: ER ercd = tk_loc_mtx ( ID mtxid, TMO tmout ) 

        解锁互斥体: ER ercd = tk_unl_mtx ( ID mtxid )  

        查询互斥体: ER ercd = tk_ref_mtx ( ID mtxid, T_RMTX ,*pk_rmtx )  



实验操

        在实验中主要还是要注意三个地方,一个是互斥体、任务建立的函数,第二个就是用于测试用的两个任务的代码,根据代码分析所得,系统先是建立了一个互斥体和任务A,B两个任务,而A,B两个任务初始的优先级都是20,而在创建互斥体的时候给互斥体的属性定义成了遵循优先级顶置协议,按任务优先级排队,同时锁定互斥体的当前任务的优先级规定为15,这都高于A和B任务的优先级,因此即使A,B两个任务的优先级有高低之分也不会在系统运行当中因为互斥体而导致死锁的情况发生,具体的代码如下:



/*
 *    Function Name : MtxSample
 *    Create Date   : 2012/09/28-2013/01/20
 *    Author    : Wangxd-Wangxd
 *    Description   : sample main program to create all tasks and mutex.
 *    Param        : None.
 *    Return Code   : TRUE-Sucess to create all task
 *                    FALSE-Fail to creat all task.
 */
ER MtxSample( void)
{
    T_CMTX cmtx;
    T_CTSK ctskA;
    T_CTSK ctskB;


    tm_putstring((UB*)"Mutex sample step 1-Create Mutex;\n");
    cmtx.exinf  = (VP)NULL;            // 无扩展信息
    cmtx.mtxatr = TA_TPRI|TA_CEILING;  // 按照优先级顺序排队,遵从优先级顶置协议
    cmtx.ceilpri = 15;                 // 互斥体顶置时的优先级
    MtxID = tk_cre_mtx(&cmtx);         // 创建互斥体
    if(MtxID>0) {
        tm_putstring((UB*)"Mutex sample create step 1-Create Mutex, ID is ");
        tm_putchar(MtxID+48);
        tm_putstring((UB*)" !\n");
    } else {
        tm_putstring((UB*)"Error code is ");
        tm_putchar(MtxID+48);
        tm_putstring((UB*)" !\n");
    }


    ctskA.exinf   = (VP)NULL;
    ctskA.tskatr  = TA_HLNG | TA_RNG0;
    ctskA.task    = MtxSampleTaskA;
    ctskA.itskpri = 20;             // 创建优先级为20的任务A
    ctskA.stksz   = 512;
    TaskID_A      = tk_cre_tsk(&ctskA);   
    if(TaskID_A>0) {
        tm_putstring((UB*)"Mutex sample create step 2-Create Task A, ID is ");
        tm_putchar(TaskID_A+48);
        tm_putstring((UB*)" !\n");
    } else {
        tm_putstring((UB*)"Error code is ");
        tm_putchar(TaskID_A+48);
        tm_putstring((UB*)" !\n");
    }


    ctskB.exinf   = (VP)NULL;
    ctskB.tskatr  = TA_HLNG | TA_RNG0;
    ctskB.task    = MtxSampleTaskB;
    ctskB.itskpri = 20;          // 创建优先级为20的任务B
    ctskB.stksz   = 512;
    TaskID_B      = tk_cre_tsk(&ctskB);
    if(TaskID_B>0) {
        tm_putstring((UB*)"Mutex sample create step 3-Create Task B, ID is ");
        tm_putchar(TaskID_B+48);
        tm_putstring((UB*)" !\n");
    } else {
        tm_putstring((UB*)"Error code is ");
        tm_putchar(TaskID_B+48);
        tm_putstring((UB*)" !\n");
    }


    tm_putstring((UB*)"Mutex sample create step 4-Start Task B;\n\n");
    tk_sta_tsk(TaskID_B,0);   // 创建完A,B两个任务后首先启动任务B


    return E_OK;

 


 /*
 *    Function Name : MtxSampleTaskA
 *    Create Date   : 2012/09/28-2013/01/20
 *    Author    : Wangxd-Wangxd
 *    Description   : Task A visits the mutex and shows information.
 *    Param        : stacd:parameter from start task
 *                  : exinf:
 *    Return Code   : None.
 */
void MtxSampleTaskA(W stacd,VP exinf)
{
tm_putstring((UB*)"Task A start successfully!\n");
while(1){
        PutTaskPriority(TaskID_A);  // 显示当前的任务优先级
tk_loc_mtx(MtxID, TMO_FEVR);    // 锁定互斥体
tm_putstring((UB*)"Task A locked the mutex successfully!\n");
        PutTaskPriority(TaskID_A);  // 再显示当前任务优先级
GlobalData = "Task A is visiting GlobalData...\n";
tm_putstring((UB*)GlobalData);
        Delay(0x1000000);
        tm_putstring((UB*)"======================================\n");
        Delay(0x1000000);
tm_putstring((UB*)"Task A will unlock the mutex!\n\n");
tk_unl_mtx(MtxID);
}
}


/*
 *    Function Name : MtxSampleTaskB
 *    Create Date   : 2012/09/28-2013/01/21
 *    Author    : Wangxd-Wangxd
 *    Description   : Task B visits the mutex and shows information.
 *    Param        : stacd:parameter from start task
 *                  : exinf:
 *    Return Code   : None.
 */
void MtxSampleTaskB(W stacd,VP exinf)
{
B c;


    tm_putstring((UB*)"Task B will start task A;\n\n");
    tk_sta_tsk(TaskID_A,0);   // 任务B中先启动任务A


while(1){
        tm_putstring((UB*)"Task B is running,input Command(e=exit):\n");
        c = tm_getchar(0);
        if(c=='e') {
       break;
        }


        PutTaskPriority(TaskID_B);   // 显示当前任务B的优先级
tk_loc_mtx(MtxID, TMO_FEVR);     // 锁定互斥体
    tm_putstring((UB*)"Task B locked the mutex successfully!\n");
        PutTaskPriority(TaskID_B);   // 再次显示当前任务B的优先级
GlobalData = "Task B is visiting GlobalData...\n";
tm_putstring((UB*)GlobalData);
        Delay(0x1000000);
        tm_putstring((UB*)"======================================\n");
        Delay(0x1000000);
tm_putstring((UB*)"Task B will unlock the mutex!\n\n");
tk_unl_mtx(MtxID);
}
tm_putstring((UB*)"Task B will delete mutex;\n");
    tk_del_mbx(MtxID);
tm_putstring((UB*)"Task B will terminate&delete task A;\n");
    tk_ter_tsk(TaskID_A);
    tk_del_tsk(TaskID_A);
tm_putstring((UB*)"Task B will terminate&delete self;\n");
    tk_exd_tsk();
}


/*
 *    Function Name : PutTaskPriority
 *    Create Date   : 2010/01/21-2013/01/21
 *    Author        : Wangxd-Wangxd
 *    Description   : refer task priority.   获取并输出任务的优先级
 *    Param         : ID taskid     task ID number
 *    Return Code   : none
 */
void PutTaskPriority(ID taskid)
{
    T_RTSK rtsk;     // 定义一个变量,可用于创建任务 
    ER ercd;         // 错误代码变量
    B tskpri[10];    // 优先级数组


    ercd = tk_ref_tsk(taskid, &rtsk);  // 获取当前任务ID对应的任务状态,并返回到rtsk指向的数据地址
    if(E_OK == ercd)
{
    if(taskid == TaskID_A)
{
       tm_putstring((UB*)"Task A");
    }
else
{
       tm_putstring((UB*)"Task B");
    }
tm_putstring((UB*)" current priority is ");
    ltostr(rtsk.tskpri,tskpri,10,10);
tm_putstring((UB*)tskpri);
tm_putstring((UB*)"\n");
    }

}



实验输出效果截图:




思考题:

    1. 如果不使用优先级顶置或优先级继承的属性,则任务B锁定互斥体后,任务自身的优先级不会发生变化,将保持在20这个优先级上面,而且实验发现同等优先级的任务A无法获取互斥体所涉及的资源。如果将A任务的优先级设置比任务B的优先级高,则任务B启动任务A后,A任务就会首先并一直占用互斥体对应的资源。

    2. 如果将其中一个任务的优先级设置得比另一个高的话,则根据互斥体设置的按照优先级排队原则,高优先级的任务会一直占用互斥体所对应的资源,而任务低的一直得不到执行,当然这只是这个例程中的效果,如果任务要处理的事务较多,则当优先级高的任务去处理其他事务,不需要锁定这个资源时,优先级低的任务将会能够锁定该互斥量。我们可以在任务A的主循环的底部加上一句ercd = tk_slp_tsk(5000);这样的话,任务B就有机会锁定互斥体对应的全局资源了。效果如下图:




高工
2013-07-31 08:11:37     打赏
30楼

7. 实验六 (消息缓冲区)    【返回开发进程列表】


1. 概念学习


        作用

       消息缓冲区通过传递大小可变的消息实现任务之间的通信功能,消息缓冲区包含有多任务应用的等待列、消息缓冲区专用的消息队列和一片消息缓冲区空间用来保存发送的消息。

        如果消息缓冲区已经有任务被排列在队列里,消息就会被传递给等待队列里的先头任务中,收到消息的任务将会从 Wait 状态迁移到 Ready 状态。

        如果消息缓冲区没有任务被排列在队列中,消息就会被排列到消息队列中,发送消息的任务不进行状态迁移。 

        需要接收消息的任务对消息缓冲区发行 tk_rcv_mbf 系统调用,如果消息缓冲区中已经有消息排列在队列里时,任务就会收取排列在队列里的消息。如果消息缓冲区中还没有消息被排列在队列中,任务就不能继续处理,被排列在消息缓冲区的任务等待队列中,任务会迁移到 Wait 状态。在处于 Wait 状态过程中,如果从其他任务得到消息,可以接收消息,任务同时也会从 Wait 状态解脱出来,迁移到 Ready 状态。 

        构成

        发送 / 接收消息的任务队列,等待接收消息的任务队列: FIFO 或 Priority 方式 

         消息缓冲区:系统自动分配或用户指定区域 TA_USERBUF 

        相关函数

        创建消息缓冲区: ID mbfid = tk_cre_mbf(T_CMBF * pk_cmbf) 

        删除消息缓冲区: ER ercd = tk_del_mbf(ID mbfid) 

        发送消息到消息缓冲区: ER ercd = tk_snd_mbf(ID mbfid, VP msg, INT msgsz, TMO tmout) 

        接收消息缓冲区的消息: INT msgsz = tk_rcv_mbf(ID mbfid, VP msg, TMO tmout) 

        查询消息缓冲区: ER ercd = tk_ref_mbf(ID mbfid, T_RMBF *pk_rmbf) 



2. 实验操作

        相关实验代码如下:

/*
 *    Function Name : MbfSample
 *    Create Date   : 2012/12/10-2013/6/7
 *    Author        : Cuihl-Wangxd
 *    Description   : sample main program to create two tasks and two message buffers.
 *    Param        : None.
 *    Return Code   : TRUE - Success to create all tasks and message buffers.
 *                    FALSE- Fail to create one of all tasks and message buffers .
 */
ER MbfSample( void)
{
    ER ercd=E_OK;
    T_CTSK ctsk;
    T_CMBF cmbf;


    tm_putstring((UB*)"Message buffer sample create step 1-Create Task A.\n");
    ctsk.exinf = (VP)NULL;
    ctsk.tskatr = TA_HLNG|TA_RNG0;  // 高级语言,任务保护级别为TA_RNG0
    ctsk.task = MbfSampleTaskA;
    ctsk.itskpri = 18;    // 创建优先级为18的任务A
    ctsk.stksz = 512;
    TaskID_A = tk_cre_tsk(&ctsk);  // 创建任务A
    if(TaskID_A < E_OK) {
    ercd=TaskID_A;
        return ercd;
    }
    
    tm_putstring((UB*)"Message buffer sample create step 2-Create Task B.\n");
    ctsk.exinf = (VP)NULL;
    ctsk.tskatr = TA_HLNG|TA_RNG0;
    ctsk.task = MbfSampleTaskB;
    ctsk.itskpri = 20;   // 创建优先级为20的任务B
    ctsk.stksz = 512;
    TaskID_B = tk_cre_tsk(&ctsk);
    if(TaskID_B < E_OK) {
    ercd=TaskID_B;
        return ercd;
    }
    
    tm_putstring((UB*)"Message buffer sample create step 3-Create the first message buffer.\n");
    cmbf.exinf = (VP)NULL;
    cmbf.mbfatr = TA_TFIFO;
    cmbf.bufsz = MBF1SIZE;
    cmbf.maxmsz = MBF1MAXMSIZE;     // MBF1MAXMSIZE的值为80,以字节为单位
    cmbf.bufptr = (VP)NULL; /*when  member bufptr(cmbf.bufptr) is evaluated with TA_USERBUF */


    MbfID_1 = tk_cre_mbf(&cmbf);
    if(MbfID_1 < E_OK){
    ercd=MbfID_1;
        return ercd;
    }


    tm_putstring((UB*)"Message buffer sample create step 4-Create the second message buffer.\n");
    cmbf.exinf = (VP)NULL;
    cmbf.mbfatr = TA_TFIFO;
    cmbf.bufsz = MBF2SIZE;
    cmbf.maxmsz = MBF2MAXMSIZE;    // 也是80个字节
    cmbf.bufptr = (VP)NULL; /*It is valid when  member bufptr(cmbf.bufptr) is evaluated with TA_USERBUF */


    MbfID_2 = tk_cre_mbf(&cmbf);
    if(MbfID_2 < E_OK){
    ercd=MbfID_2;
        return ercd;
    }


    tm_putstring((UB*)"Message buffer sample create step 5-Start Task A !\n");
    ercd = tk_sta_tsk(TaskID_A,0);    // 启动任务A
if (E_OK != ercd){
tm_putstring((UB*)"start Task A failed!!!\n");
}
    return TRUE;

 
/*
 *    Function Name : MbfSampleTaskA
 *    Create Date   : 2012/12/11-2013/5/16
 *    Author    : Cuihl - cuihl
 *    Description   : Task A loop functin.
 *    Param        : stacd:parameter from start task
 *                  : exinf:
 *    Return Code   : None.
 */
void MbfSampleTaskA(W stacd,VP exinf)
{
ER ercd;
UW len;
B  c;
T_RMBF pk_rmbf;
W  msgsz;
B msg2mbf1[] = "Do you think that uTenux is the best RTOS ?\n";
B msgofmbf2[100]="\0";


tm_putstring((UB*)"Message buffer sample create step 6- Task A start Task B.\n");
ercd = tk_sta_tsk(TaskID_B,0);     // 启动任务B
if (E_OK != ercd){
   tm_putstring((UB*)"Task B start failed!\n");
}


for(;;){
tm_putstring((UB*)"\nTask A is running,Input Command(e=exit):\n");
c = tm_getchar(0);
if('e' == c) {
   break;
}


        len = strlen(msg2mbf1);   // 获取消息长度,用于消息发送函数对数据进行封装
tm_putstring((UB*)"Task A will send a message to the first message buffer......\n");
tm_putstring((UB*)"The message is : ");
tm_putstring((UB*)msg2mbf1);
ercd = tk_snd_mbf(MbfID_1, (VP)msg2mbf1, len, -1);    // 发送消息
if(E_OK == ercd){
tm_putstring((UB*)"Task A have successfully sent a message to the first message buffer! \n");
} else{
tm_putstring((UB*)"Task A can't send a message to the first message buffer! \n");
PutErcd(ercd);
}


tm_putstring((UB*)"Task A will receive a message from the second message buffer......\n");
ercd = tk_ref_mbf(MbfID_2, &pk_rmbf);   // 查询消息
if(E_OK == ercd){
   /*The second message buffer haven't any message */
if(pk_rmbf.frbufsz == MBF2SIZE){
  tm_putstring((UB*)"There isn't a message in the second message buffer ! \n");
  tm_putstring((UB*)"Task A is waiting......\n");
  }
}
tk_rcv_mbf(MbfID_2, (VP)msgofmbf2, -1);    // 等待并接收消息,若未等到消息便切换任务状态
    tm_putstring((UB*)"Task A is rerunning.\n");
tm_putstring((UB*)"Task A have successfully received a message from the second message buffer! \n");
tm_putstring((UB*)"The message is : ");
tm_putstring((UB*)(msgofmbf2));
tm_putstring((UB*)"\n");
}


tm_putstring((UB*)"Task A will delete message buffers.\n");
tk_del_mbf(MbfID_1);
tk_del_mbf(MbfID_2);
tm_putstring((UB*)"Task A will terminate and delete task B and task C.\n");
tk_ter_tsk(TaskID_B);
tk_del_tsk(TaskID_B);
tm_putstring((UB*)"Task A will terminate and delete self.\n");
tk_exd_tsk();
}


/*
 *    Function Name : MbfSampleTaskB
 *    Create Date   : 2012/12/11-2013/5/16
 *    Author    : Cuihl-cuihl
 *    Description   : Task B loop function.
 *    Param        : stacd:parameter from start task
 *                  : exinf:
 *    Return Code   : None.
 */
void MbfSampleTaskB(W stacd,VP exinf)
{
ER ercd;
B msgofmbf1[100]="\0";
B msg2mbf2[]= "Yes,it is the best !\n";
UW len;
T_RMBF pk_rmbf;
W  msgsz;


for(;;){
tm_putstring((UB*)"\nTask B is running.\n");
tm_putstring((UB*)"Task B will receive a message from the first message buffer....... \n");
ercd = tk_ref_mbf(MbfID_1, &pk_rmbf);   // 查询缓冲区中的消息
if(E_OK == ercd){
/*The first message buffer haven't any message */
  if(pk_rmbf.frbufsz == MBF1SIZE){
  tm_putstring((UB*)"There isn't a message in the first message buffer ! \n");
  tm_putstring((UB*)"Task B will enter the receive waiting queue of the first message buffer ! \n");
  }
}
msgsz = tk_rcv_mbf(MbfID_1, (VP)msgofmbf1, -1);   // 接收并等待消息
  if(msgsz > 0){
  tm_putstring((UB*)"Task B have successfully received a message from the first message buffer! \n");
    tm_putstring((UB*)"The message is : ");
    tm_putstring((UB*)(msgofmbf1));
  }else{
    tm_putstring((UB*)"Task B can't receive a message from the first message buffer! \n");
  }


len = strlen(msg2mbf2);
tm_putstring((UB*)"Task B will send a message to the second message buffer......\n");
tm_putstring((UB*)"The message is : ");
tm_putstring((UB*)msg2mbf2);
tm_putstring((UB*)"\n");
ercd = tk_snd_mbf(MbfID_2, (VP)msg2mbf2, len, -1);   // 发送消息2
if(E_OK != ercd){
tm_putstring((UB*)"Task B can't send a message to the second message buffer! \n");
PutErcd(ercd);
}
    }
}



实验结果截图:





思考题:

1. 当一个缓冲区内有多条消息时取出的消息是最最先进入缓冲区的消息。

2. 消息缓冲区满后,该任务准备要发送的消息将会在发送队列中等待,直到消息缓冲区中有可用的空间。


共46条 3/5 1 2 3 4 5 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]